package org.arain.spring.captive.portal.server;

import java.net.InetAddress;
import java.net.InetSocketAddress;

import org.arain.spring.captive.portal.utils.EhcacheUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.dns.DatagramDnsQuery;
import io.netty.handler.codec.dns.DatagramDnsResponse;
import io.netty.handler.codec.dns.DefaultDnsQuestion;
import io.netty.handler.codec.dns.DefaultDnsRawRecord;
import io.netty.handler.codec.dns.DnsRecordType;
import io.netty.handler.codec.dns.DnsSection;

/**
 * 
 * <p>
 * Title:UDPHandler
 * </p>
 * 
 * @author Arain
 * @date2018年8月10日
 */
@Component
@Qualifier("uDPHandler")
@ChannelHandler.Sharable
public class UDPHandler extends SimpleChannelInboundHandler<DatagramDnsQuery> {

	@Autowired
	private EhcacheUtil ehcacheUtil;

	@Value("${gateway.ip}")
	private String ip;

	private static final Logger logger = LoggerFactory.getLogger(UDPHandler.class);

	@Override
	protected void channelRead0(ChannelHandlerContext ctx, DatagramDnsQuery query) throws Exception {

		DatagramDnsResponse response = new DatagramDnsResponse(query.recipient(), query.sender(), query.id());
		try {
			DefaultDnsQuestion dnsQuestion = query.recordAt(DnsSection.QUESTION);
			response.addRecord(DnsSection.QUESTION, dnsQuestion);
			InetSocketAddress recipient = response.recipient();
			logger.info(query.sender() + "Query Name：" + dnsQuestion.name() + "  ip:" + recipient);
			ByteBuf buf = null;
			String hostAddress = recipient.getAddress().getHostAddress();
			logger.info("IP:" + hostAddress);
			Object object = ehcacheUtil.get("timeCache", hostAddress);
			if (StringUtils.isEmpty(object)) {
				logger.info("gateway-ip:{}", ip);
				byte[] targt = new byte[4];
				String[] split = ip.split("\\.");
				for (int i = 0; i < split.length; i++) {
					targt[i] = (byte) Integer.parseInt(split[i]);
				}
				// byte[] targt = new byte[] { (byte) 192, (byte) 168, (byte) 137, 1 };
				buf = Unpooled.wrappedBuffer(targt);
				addRecord(response, dnsQuestion, buf);
			} else {
				InetAddress[] addresses = InetAddress.getAllByName(dnsQuestion.name());
				for (InetAddress inetAddr : addresses) {
					logger.info("转发:" + inetAddr.toString() + "--" + inetAddr.getHostName());
					buf = Unpooled.wrappedBuffer(inetAddr.getAddress());
					addRecord(response, dnsQuestion, buf);
				}
			}
		} catch (Exception e) {
			logger.info(e.getMessage());
		} finally {
			ctx.writeAndFlush(response);
		}
	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
		cause.printStackTrace();
	}

	private DatagramDnsResponse addRecord(DatagramDnsResponse response, DefaultDnsQuestion dnsQuestion, ByteBuf buf) {
		DefaultDnsRawRecord queryAnswer = new DefaultDnsRawRecord(dnsQuestion.name(), DnsRecordType.A, 3600, buf);
		DatagramDnsResponse addRecord = response.addRecord(DnsSection.ANSWER, queryAnswer);
		return addRecord;
	}
}
